module GameLoop where

import Evaluator2
import Data.List
import Control.Monad


data App = LeftApp {ap_function :: Function, ap_slot :: Int} | RightApp {ap_slot :: Int, ap_function :: Function} deriving (Eq, Show)

($>) = LeftApp
(<$) = RightApp

apply (LeftApp f i) = \s -> left_app s f i
apply (RightApp i f) = \s ->  right_app s i f

-- Режим для одного игрока

single_game_loop :: [App] -> IO GameState
single_game_loop = loop1' 1 init_game_state

loop1' k state [] = putStrLn "no more commands" >> return state
loop1' k state (ap:apps) = do
  putStrLn $ "##### turn " ++ show k
  state' <- apply_step state ap
  loop1' (k+1) state' apps

-- Режим для двух игроков
duel_game_loop :: [App] -> [App] -> IO GameState
duel_game_loop = loop2' 1 init_game_state

loop2' k state (ap1:apps1) (ap2:apps2) = do
  putStrLn $ "##### turn " ++ show k
  putStrLn "*** player1 turn"
  state' <- apply_step state ap1
  -- Обмениваем игроков, и второй полуход
  let mirror_state = swap_players state'
  putStrLn "*** player2 turn"
  mirror_state' <- apply_step mirror_state ap2
  let state' = swap_players mirror_state'
  loop2' (k+1) state' apps1 apps2

loop2' _ state [] [] = putStrLn "no more commands" >> return state
loop2' _ state _ _ = putStrLn "warning, one of lists finished" >> return state

-- Применение одного хода с распечаткой результатов
apply_step :: GameState -> App -> IO GameState
apply_step state ap = do
  let g = apply ap
  let (res, state') = g state
  print ap
  print state'
  print res
  return state'